package logging

import (
	"fmt"
	"log"
	"os"
	"path/filepath"
	"runtime"

	"github.com/json-iterator/go"
)

type Level int

var json = jsoniter.ConfigCompatibleWithStandardLibrary

type logFormat struct {
	AppName string `json:"appName"`
	Code    string `json:"code"`
	Time    string `json:"time"`
	Desc    string `json:"desc"`
}

type conloseLog struct {
	Time     string `json:"time"`
	Code     int    `json:"code"`
	Latency  string `json:"latency"`
	ClientIP string `json:"clientIp"`
	Method   string `json:"method"`
	Path     string `json:"path"`
	Comment  string `json:"comment"`
}

var (
	F                  *os.File
	DefaultPrefix      = ""
	DefaultCallerDepth = 2
	logger             *log.Logger
	logPrefix          = ""
	levelFlags         = []string{"DEBUG", "INFO", "WARN", "ERROR", "FATAL", "PRINT"}
)

const (
	DEBUG Level = iota
	INFO
	WARNING
	ERROR
	FATAL
	PRINT
)

func setFlag(flag string) {
	filePath := getLogFileFullPath(flag)
	F = openLogFile(filePath)

	logger = log.New(F, DefaultPrefix, log.LstdFlags|log.Lshortfile)
}

func Debug(appName, code, time, desc string) {
	setFlag(LogSaveName)
	log := &logFormat{
		AppName: appName,
		Code:    code,
		Time:    time,
		Desc:    desc,
	}
	marshal, _ := json.Marshal(log)
	setPrefix(DEBUG)
	logger.Println("|" + string(marshal))
}

func Info(appName, code, time, desc string) {
	setFlag(LogSaveName)

	log := &logFormat{
		AppName: appName,
		Code:    code,
		Time:    time,
		Desc:    desc,
	}
	marshal, _ := json.Marshal(log)
	setPrefix(INFO)
	logger.Println("|" + string(marshal))

}

func Warn(appName, code, time, desc string, v ...interface{}) {
	setFlag(LogSaveName)

	log := &logFormat{
		AppName: appName,
		Code:    code,
		Time:    time,
		Desc:    desc,
	}
	marshal, _ := json.Marshal(log)
	setPrefix(WARNING)
	logger.Println("|" + string(marshal))
}

func Error(appName, code, time, desc string) {
	setFlag(LogSaveName)

	log := &logFormat{
		AppName: appName,
		Code:    code,
		Time:    time,
		Desc:    desc,
	}
	marshal, _ := json.Marshal(log)
	setPrefix(ERROR)
	logger.Println("|" + string(marshal))

}

func Fatal(appName, code, time, desc string) {
	setFlag(LogSaveName)

	log := &logFormat{
		AppName: appName,
		Code:    code,
		Time:    time,
		Desc:    desc,
	}
	marshal, _ := json.Marshal(log)
	setPrefix(FATAL)
	logger.Println("|" + string(marshal))
}

// Println
func Println(time, latency, clientIp, method, path, comment string, code int) {
	setFlag("conlose")

	log := &conloseLog{
		Time:     time,
		Code:     code,
		Latency:  latency,
		ClientIP: clientIp,
		Method:   method,
		Path:     path,
		Comment:  comment,
	}
	marshal, _ := json.Marshal(log)
	logger.Println("|" + string(marshal))

}

func setPrefix(level Level) {
	_, file, line, ok := runtime.Caller(DefaultCallerDepth)

	if ok {
		logPrefix = fmt.Sprintf("[%s]{%s : %d}", levelFlags[level], filepath.Base(file), line)
	} else {
		logPrefix = fmt.Sprintf("{%s}", levelFlags[level])
	}

	logger.SetPrefix(logPrefix)
}
